Skip to content

feat: add PyPI publishing workflow and readme metadata#2915

Open
mnriem wants to merge 13 commits into
mainfrom
mnriem/feat-2908-pypi-publishing
Open

feat: add PyPI publishing workflow and readme metadata#2915
mnriem wants to merge 13 commits into
mainfrom
mnriem/feat-2908-pypi-publishing

Conversation

@mnriem

@mnriem mnriem commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds infrastructure for publishing specify-cli to PyPI, addressing #2908.

Changes

  1. pyproject.toml — adds readme = "README.md" so PyPI displays the project description
  2. .github/workflows/publish-pypi.yml — new manual workflow for publishing to PyPI
  3. .github/workflows/release.yml — updates install instructions to prefer uv tool install specify-cli@latest

Publish Workflow Design

  • Manual trigger (workflow_dispatch) — run after the release workflow completes
  • Tag input — specify which release tag to publish (e.g., v0.10.1)
  • Validation — verifies tag format and that it matches pyproject.toml version
  • Trusted publishers (OIDC) — no API tokens needed; uses id-token: write permission
  • Protected environment — requires a pypi GitHub environment for deployment gating
  • Two-job split — build (no elevated permissions) → publish (OIDC only)

Prerequisites Before First Use

Testing

This workflow won't run until manually triggered with a valid tag, so it's safe to merge ahead of the PyPI ownership transfer.

- Add readme = "README.md" to pyproject.toml for PyPI project description
- Add manual publish-pypi.yml workflow using trusted publishers (OIDC)
- Update release.yml install instructions to prefer PyPI

The publish workflow is manually triggered after a release, checks out the
specified tag, verifies version consistency, builds with uv, and publishes
using trusted publishing (no API tokens required).

Prerequisites before first use:
- Take ownership of the specify-cli PyPI project (#2908)
- Create a 'pypi' environment in repo settings
- Configure trusted publisher on PyPI for this repo/workflow

Closes #2908

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 10, 2026 13:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds release infrastructure to publish specify-cli to PyPI and improve the package’s PyPI description rendering, aligning with the goal that uv tool install specify-cli@latest works reliably.

Changes:

  • Add readme = "README.md" to pyproject.toml so PyPI renders the README.
  • Introduce a manual GitHub Actions workflow to build and publish to PyPI via trusted publishing (OIDC).
  • Update release notes generation to prefer uv tool install specify-cli@latest, with a source-install fallback.
Show a summary per file
File Description
pyproject.toml Adds README metadata for PyPI rendering.
.github/workflows/publish-pypi.yml New manual build+publish workflow using artifacts + OIDC trusted publishing.
.github/workflows/release.yml Updates generated release install instructions to prefer PyPI installs.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 3

Comment thread .github/workflows/publish-pypi.yml
Comment thread .github/workflows/publish-pypi.yml
Comment thread .github/workflows/publish-pypi.yml
- Add actions: read permission (required for artifact upload/download)
- Move version check after uv install and use uv run python (ensures
  Python >=3.11 with tomllib is available regardless of runner image)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@youngjoel

Copy link
Copy Markdown

Note that PyPI does not host image files, so relative image paths from your local repository (e.g., My Image) will appear broken. To fix this, you must change your image URLs to absolute paths pointing to an external file host, such as the ://githubusercontent.com URL for your repository.

You can see this here: https://pypi.org/project/specify-cli/ , where the Spec Kit logo isn't rendered.

pypi/warehouse#5246

PyPI does not host images from the repository, so relative paths like
./media/logo.webp render as broken images. Switch to absolute
raw.githubusercontent.com URLs so images display on both GitHub and PyPI.

Ref: pypi/warehouse#5246

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 10, 2026 20:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 4

Comment thread README.md
Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/publish-pypi.yml Outdated
Comment thread .github/workflows/publish-pypi.yml Outdated
- Convert remaining /media/ image path to absolute URL for PyPI
- Pin release install to specific version (specify-cli==X.Y.Z)
- Align setup-uv to v8.2.0 matching rest of CI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

Comment thread .github/workflows/publish-pypi.yml
Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml
- Use job-level permissions: actions:write on build (for upload-artifact),
  actions:read on publish (for download-artifact)
- Include both @latest and pinned version in release notes
- Add note that PyPI may lag behind the GitHub release

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment thread .github/workflows/publish-pypi.yml
Comment thread .github/workflows/release.yml Outdated
- Build job needs contents:read for checkout (job-level perms replace
  workflow-level)
- Clarify that PyPI publishing is manually triggered, not automatic

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

The new publish workflow should force checkout of refs/tags/<tag> (not a potentially ambiguous ref) to avoid publishing from an unintended branch with the same name.

Copilot's findings
  • Files reviewed: 4/4 changed files
  • Comments generated: 1

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread .github/workflows/publish-pypi.yml Outdated
Move tag format validation before checkout and use refs/tags/ prefix
to ensure we always check out a tag, not a branch with the same name.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

The release notes currently recommend an invalid uv tool install ...@latest command, and the publish workflow would benefit from pinning Python explicitly for deterministic builds/version parsing.

Copilot's findings
  • Files reviewed: 4/4 changed files
  • Comments generated: 3

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread .github/workflows/release.yml Outdated
Comment thread README.md
Comment thread .github/workflows/publish-pypi.yml
- Convert all relative .md links in README to absolute GitHub URLs
  for PyPI rendering compatibility
- Fix release notes: use 'uv tool install specify-cli' (no @latest)
- Pin Python 3.13 via uv python install for deterministic builds
  and use python3 directly instead of uv run

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

The new publish workflow likely won’t run as written (uv publish --trusted-publishing always), and the updated release notes can direct users to install an unaffiliated PyPI package prior to ownership transfer (supply-chain risk).

Copilot's findings
  • Files reviewed: 4/4 changed files
  • Comments generated: 6

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread .github/workflows/publish-pypi.yml Outdated
Comment thread .github/workflows/publish-pypi.yml Outdated
Comment thread .github/workflows/publish-pypi.yml Outdated
Comment thread .github/workflows/release.yml Outdated
Comment thread README.md Outdated
Comment thread .github/workflows/release.yml Outdated
- Use actions/setup-python (pinned v6, Python 3.13) instead of
  uv python install for deterministic builds
- Use python instead of python3 for setup-python compatibility
- Remove unsupported --trusted-publishing always flag from uv publish
  (OIDC is auto-detected with id-token: write)
- Update README install to lead with PyPI, source as fallback
- Update installation guide: replace PyPI disclaimer with official
  package note, add PyPI as primary install method
- Release notes: pin to exact version, clarify PyPI timing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

The updated docs/README wording implies PyPI availability/ownership immediately, but the PR itself describes prerequisites and a post-release publish step—documentation should be conditioned to avoid misleading installs right after merge.

Copilot's findings
  • Files reviewed: 5/5 changed files
  • Comments generated: 2

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread README.md Outdated
Comment thread docs/installation.md Outdated
- README: note source install is useful when PyPI version lags
- Installation guide: explain PyPI follows GitHub releases and may
  lag briefly; source installs are always immediately available

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

The generated release notes use an invalid uv tool install version pin syntax (==), which is likely to fail when users follow the instructions.

Copilot's findings
  • Files reviewed: 5/5 changed files
  • Comments generated: 1

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread .github/workflows/release.yml
uv tool install accepts PEP 508 specifiers when quoted. Add quotes
around 'specify-cli==VERSION' so users can copy-paste directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

The updated install instructions should consistently use uv tool install specify-cli@latest (per the PR/issue goal) to avoid stale installs due to uv caching.

Copilot's findings
  • Files reviewed: 5/5 changed files
  • Comments generated: 3

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread README.md Outdated
Comment thread docs/installation.md Outdated
Comment thread .github/workflows/release.yml
Use @latest to force a fresh PyPI resolve (bypasses uv's cached tool
version), matching the issue acceptance criteria. Source install remains
as fallback when PyPI lags.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

A few user-facing instructions and workflow safety/clarity issues should be addressed to keep release docs reproducible and the publish workflow fail-fast on missing artifacts.

Copilot's findings
  • Files reviewed: 5/5 changed files
  • Comments generated: 3

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread .github/workflows/release.yml
Comment thread docs/installation.md Outdated
Comment thread .github/workflows/publish-pypi.yml
Release notes (versioned changelog) must always reference the specific
release version, not @latest. Use 'specify-cli==VERSION' for
reproducibility.

Also clarify that PyPI publishing is 'performed after' (not 'follows')
each release, making the manual nature clearer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

README/docs currently present PyPI installs as “official” even though the PR/issue context indicates PyPI ownership/publishing may not be in place at merge time, which can mislead users into installing an unaffiliated package.

Copilot's findings
  • Files reviewed: 5/5 changed files
  • Comments generated: 2

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread docs/installation.md
Comment on lines +13 to 15
> [!NOTE]
> The official `specify-cli` package is published to [PyPI](https://pypi.org/project/specify-cli/) by the [github/spec-kit](https://github.com/github/spec-kit) maintainers. PyPI publishing is performed after each GitHub release and may lag briefly. Source installs from the GitHub repository are always available immediately.

Comment thread README.md
Comment on lines +47 to +51
Requires **[uv](https://docs.astral.sh/uv/)** ([install uv](https://github.com/github/spec-kit/blob/main/docs/install/uv.md)):

```bash
uv tool install specify-cli@latest
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants